package ru.averta.notes.other;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.ClassUtils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.util.*;

@Service
public class UtilsCommon {

    private static final Logger logger = LoggerFactory.getLogger(UtilsCommon.class);

    @Value("${common.fileRootPath}")
    private String fileRootPath;

    private static ApplicationContext context;

    /**
     * Загружаем spring context как статическое поле
     * @param context
     */
    @Autowired public void setApplicationContext(ApplicationContext context) {
        UtilsCommon.context = context;
    }

    public static Object getBean(String title) {
        return context.getBean(title);
    }

    public static <T> T getBean(java.lang.Class<T> tClass) {
        return context.getBean(tClass);
    }

    /**
     *
     * @return Возвращает путь до папки, в которую сохраняются все файлы
     */
    public String getFileRootPath() {
        return fileRootPath;
    }

    public static String getClassName(Object object) {
        Class<?> typeClass = ClassUtils.getUserClass(object.getClass());
        return typeClass.getName();
    }

    public static <E> Collection<E> collectionToRemove(Collection<E> sourceCollection) {

        Collection<E> toRemove = new LinkedList<E>();
        for (E object : sourceCollection) {
            toRemove.add(object);
        }

        return toRemove;
    }

    public static Object initObject(Class clazz) {
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    public static Reader stringToReader(String source) {
        return new BufferedReader(new InputStreamReader(IOUtils.toInputStream(source)));
    }

    public static StringReader toStringReader(Reader reader) {
        if (reader instanceof StringReader) {
            return (StringReader) reader;
        } else {
            return new StringReader(readerToString(reader));
        }
    }

    public static String readerToString(Reader reader) {
        try {
            String answer = IOUtils.toString(reader);
            try {
                reader.reset();
                return answer;
            } catch (Exception e) {
                return answer;
            }
        } catch (/*IO*/Exception e) {
            logger.error("Ошибка при конвертировании из Reader в String", e);
            return "";
        }
    }

    public static Collection<Set<String>> getCombinations(ArrayList<String> source) {
        return getCombinations(source, 0);
    }

    private static Collection<Set<String>> getCombinations(ArrayList<String> source, int start) {
        Collection<Set<String>> result = new HashSet<Set<String>>();

        for (int i = start; i < source.size(); i++) {
            String currentObject = source.get(i);

            Set<String> r = new HashSet<String>();
            r.add(currentObject);
            result.add(r);

            for (int k = i; k < source.size(); k++) {
                Collection<Set<String>> subResults = getCombinations(source, start + 1);
                for (Set<String> subResult : subResults) {
                    subResult.add(currentObject);
                    result.add(subResult);
                }

            }
        }
        return result;
    }

    public static boolean checkNotEmpty(String source) {
        return (!(source == null || source.equals("")));
    }
}
